/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.jitengine.expressions.utility;

import com.fasterxml.jackson.core.type.TypeReference;
import com.inspur.edp.web.common.serialize.SerializeUtility;
import com.inspur.edp.web.common.utility.StringUtility;
import com.inspur.edp.web.formmetadata.metadata.formdom.FormDOM;
import com.inspur.edp.web.jitengine.expressions.ModuleSchemaEntities;
import com.inspur.edp.web.jitengine.expressions.ModuleSchemaEntityType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * description: 表达式定义utility
 *
 * @author Noah Guo
 * @date 2021/01/07
 */
public class ExpressionUtility {

    /// <summary>
    ///  构造表达式对应的清单文件名称
    /// </summary>
    /// <param name="moduleCode"></param>
    /// <returns></returns>
    public static String getExpressionManifestJsonPath(String moduleCode) {
        return "form.manifest.json";
    }

    /// <summary>
    ///  获取表单对应的表达式文件名称
    /// </summary>
    /// <param name="uniqueID"></param>
    /// <param name="moduleCode"></param>
    /// <returns></returns>
    public static String getExpressionFormJsonPath(String uniqueID, String moduleCode) {
        String jsonPath = "";
        if (!StringUtility.isNullOrEmpty(uniqueID)) {
            jsonPath = jsonPath + uniqueID.toLowerCase() + "-";
        }
        if (!StringUtility.isNullOrEmpty(moduleCode)) {
            jsonPath = jsonPath + moduleCode.toLowerCase();
        }
        jsonPath = jsonPath + ".expression.json";
        return jsonPath;
    }

    /// <summary>
    /// 构造表单对应的namespace
    /// </summary>
    /// <param name="externalComponentCode"></param>
    /// <param name="moduleCode"></param>
    /// <returns></returns>
    public static String getNameSpace(String externalComponentCode, String moduleCode) {
        String strNameSpace = "";
        if (!StringUtility.isNullOrEmpty(externalComponentCode)) {
            strNameSpace += externalComponentCode + "_";
        }
        if (!StringUtility.isNullOrEmpty(moduleCode)) {
            strNameSpace += moduleCode;
        }
        return strNameSpace;
    }


    public static com.inspur.edp.web.jitengine.expressions.FieldInfo getFieldInfoById(String fieldId, FormDOM formDom) {
        if (formDom == null || formDom.getModule() == null || formDom.getModule().getSchemas() == null || formDom.getModule().getSchemas().size() == 0 ||
                formDom.getModule().getviewmodels() == null || formDom.getModule().getviewmodels().size() == 0) {
            return null;
        }
        com.inspur.edp.web.jitengine.expressions.FieldInfo fieldInfo = null;
        String serializedModuleEntities = SerializeUtility.getInstance().serialize(formDom.getModule().getSchemas().get(0).get("entities"), false);
        List<ModuleSchemaEntities> temp = new ArrayList<>();
        List<ModuleSchemaEntities> schemaEntities = SerializeUtility.getInstance().deserialize(serializedModuleEntities, new TypeReference<List<ModuleSchemaEntities>>() {
        });
        if (schemaEntities == null || schemaEntities.size() == 0) {
            return null;
        }

        for (HashMap<String, Object> viewModel : formDom.getModule().getviewmodels()) {
            if ("/".equals(viewModel.get("bindTo").toString()) && (!viewModel.containsKey("parent") || viewModel.get("parent") == null)) {

            } else {
                String originalBindTo = viewModel.get("bindTo").toString();
                int splitIndex = originalBindTo.indexOf("/");
                if (splitIndex == 0) {
                    originalBindTo = originalBindTo.substring(splitIndex + 1);
                }
                TableFieldsInfo tableFieldsInfo = getTableFieldsByBindTo(schemaEntities, viewModel.get("bindTo").toString(), originalBindTo);

                if (tableFieldsInfo != null && tableFieldsInfo.getFields() != null && tableFieldsInfo.getFields().size() > 0) {

                    FieldByIDAndVMIDResult result = getFieldByIDAndVMID(tableFieldsInfo, fieldId, "");
                    if (result != null && result.getSchemaField() != null) {
                        fieldInfo = new com.inspur.edp.web.jitengine.expressions.FieldInfo();
                        fieldInfo.setSchemaFields(result.getSchemaField());
                        fieldInfo.setRelatedEntity(tableFieldsInfo.getRelatedEntity());
                        fieldInfo.setBindTo(tableFieldsInfo.getBindTo());
                        fieldInfo.setRefElementLabelPath(result.getRefElementLabelPath());
                        return fieldInfo;
                    }
                }
            }
        }

        return fieldInfo;
    }

    private static TableFieldsInfo getTableFieldsByBindTo(List<ModuleSchemaEntities> entities, String bindTo, String originalBindTo) {
        String initBindTo = bindTo;
        TableFieldsInfo tableFieldsInfo = new TableFieldsInfo();
        List<HashMap<String, Object>> tableFields = new ArrayList<>();
        if (entities == null || entities.size() == 0) {
            tableFieldsInfo.setFields(tableFields);
            tableFieldsInfo.setBindTo(originalBindTo);
            return tableFieldsInfo;
        }
        int splitIndex = bindTo.indexOf("/");
        if (splitIndex > -1) {
            bindTo = bindTo.substring(splitIndex + 1);
        }
        String finalBindTo = bindTo;
        for (ModuleSchemaEntities entity : entities) {
            ModuleSchemaEntityType entityType = entity.getType();
            if (entityType == null) {
                tableFieldsInfo.setFields(tableFields);
                tableFieldsInfo.setRelatedEntity(entity);
                tableFieldsInfo.setBindTo(originalBindTo);
                return tableFieldsInfo;
            }
            if ("".equals(finalBindTo) || finalBindTo.equals(entity.getCode()) || finalBindTo.equals(entity.getLabel())) {
                tableFieldsInfo.setFields(entityType.getFields());
                tableFieldsInfo.setRelatedEntity(entity);
                tableFieldsInfo.setBindTo(originalBindTo);
                return tableFieldsInfo;
            }
            List<ModuleSchemaEntities> entityObj = entityType.getEntities();

            if (entityObj != null && entityObj.size() > 0) {
                TableFieldsInfo tableFieldsInfoByBindTo = ExpressionUtility.getTableFieldsByBindTo(entityObj, finalBindTo, originalBindTo);
                if (tableFieldsInfoByBindTo != null && tableFieldsInfoByBindTo.getFields() != null) {
                    tableFieldsInfo.setFields(tableFieldsInfoByBindTo.getFields());
                    tableFieldsInfo.setRelatedEntity(tableFieldsInfoByBindTo.getRelatedEntity());
                    tableFieldsInfo.setBindTo(originalBindTo);
                    return tableFieldsInfoByBindTo;
                }
            }
        }
        return tableFieldsInfo;
    }

    private static FieldByIDAndVMIDResult getFieldByIDAndVMID(TableFieldsInfo tableFieldsInfo, String id, String refElementLabelPath) {
        return rescureGetFieldByIDAndVMID(tableFieldsInfo, id, refElementLabelPath);
    }

    private static FieldByIDAndVMIDResult rescureGetFieldByIDAndVMID(TableFieldsInfo tableFieldsInfo, String id, String refElementLabelPath) {
        Object element = new HashMap<String, Object>();
        boolean isRefElement = false;
        if (StringUtility.isNullOrEmpty(refElementLabelPath)) {
            refElementLabelPath = "";
        }

        String parentLabel = !StringUtility.isNullOrEmpty(refElementLabelPath) ? refElementLabelPath + "/" : "";
        for (HashMap<String, Object> field : tableFieldsInfo.getFields()) {
            if (field.get("id").equals(id)) {
                element = field;
                refElementLabelPath = parentLabel + field.get("label");
                isRefElement = !StringUtility.isNullOrEmpty(parentLabel);
                break;
            } else {
                // 关联字段/UDT字段
                if (field.containsKey("type") && field.get("type") != null) {
                    HashMap<String, Object> fieldTypeMap = (HashMap<String, Object>) field.get("type");
                    if (fieldTypeMap.containsKey("fields") && fieldTypeMap.get("fields") != null) {

                        TableFieldsInfo udtTableFieldInfo = new TableFieldsInfo();
                        udtTableFieldInfo.setFields((List<HashMap<String, Object>>) fieldTypeMap.get("fields"));
                        udtTableFieldInfo.setRelatedEntity(tableFieldsInfo.getRelatedEntity());

                        FieldByIDAndVMIDResult childResult = rescureGetFieldByIDAndVMID(udtTableFieldInfo, id, parentLabel + (field.get("label").toString()));
                        if (childResult != null && childResult.getSchemaField() != null && (childResult.getSchemaField() instanceof HashMap)) {
                            HashMap<String, Object> temper = (HashMap<String, Object>) childResult.getSchemaField();
                            if (temper != null && !temper.isEmpty()) {
                                element = childResult.getSchemaField();
                                refElementLabelPath = childResult.getRefElementLabelPath();
                                isRefElement = childResult.isRefElement();
                                break;
                            }
                        }
                    }

                }
            }
        }

        // 如果未获取到字段信息
        if (!(element instanceof HashMap)) {
            return null;
        }
        HashMap<String, Object> hashMapElement = (HashMap<String, Object>) element;
        if (hashMapElement == null || hashMapElement.isEmpty()) {
            return null;
        }

        FieldByIDAndVMIDResult fieldByIDAndVMIDResult = new FieldByIDAndVMIDResult();
        fieldByIDAndVMIDResult.setRefElement(isRefElement);
        fieldByIDAndVMIDResult.setRefElementLabelPath(refElementLabelPath);
        fieldByIDAndVMIDResult.setSchemaField(element);
        fieldByIDAndVMIDResult.setRelatedEntity(tableFieldsInfo.getRelatedEntity());

        return fieldByIDAndVMIDResult;
    }

}





